﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Globalization;
using System.Data;

using System.Text;

namespace ReconUI
{
    public partial class AuthorizeInvoice : System.Web.UI.Page
    {
        //process type enumeration to determine the type of process being carried out.
        private enum ProcessType
        {
            Authorize,
            Reject
        }

        protected void Page_Load(object sender, EventArgs e)
        {
            if (((UserVO)Session["CurrentUserVO"]) == null)
            {
                Response.Redirect("ReconSignIn.aspx");
            }
            if (!Page.IsPostBack)
            {
                GetUnauthorizedInvoiceList();
            }
        }

        protected void btnAuthorize_Click(object sender, EventArgs e)
        {
            ProcessInvoices(ProcessType.Authorize);
        }

        protected void btnReject_Click(object sender, EventArgs e)
        {
            ProcessInvoices(ProcessType.Reject);
        }

        protected void grdAuthList_PageIndexChanging(object sender, GridViewPageEventArgs e)
        {
            grdAuthList.DataSource = (DataTable)Session[SessionStore.UnAuthorizedList];
            grdAuthList.PageIndex = e.NewPageIndex;
            grdAuthList.DataBind();
        }

        private void GetUnauthorizedInvoiceList()
        {
            DBFactory db = new DBFactory();
            DataTable dtAuthList = db.GetUnauthorizedInvoices(((UserVO)Session["CurrentUserVO"]).customerId);

            DataTable dt = dtAuthList.Copy();
            dt.Columns.Add("match_unique_key", typeof(System.Int32));
            dt.Rows.Clear();

            string[] matchPatterns = new string[dtAuthList.Rows.Count];
            int matchUniqueKey = 0;

            for (int x = 0; x < dtAuthList.Rows.Count; x++)
            {
                //match pattern consisting of invoice and statement ids separated by |
                matchPatterns[x] = "~" + dtAuthList.Rows[x][0] + "~|~" + dtAuthList.Rows[x][1] + "~";
                matchUniqueKey++;
                //add the row to new table
                DataRow dr = dt.NewRow();
                for (int n = 0; n <= 9; n++)
                {
                    dr[n] = dtAuthList.Rows[x][n];
                }
                dr[10] = matchUniqueKey;
                dt.Rows.Add(dr);
                //iterate downwards to find all matches in the match group.
                for (int y = x + 1; y < dtAuthList.Rows.Count; y++)
                {
                    //separate out invoices and statements
                    string[] matchBreakUp = matchPatterns[x].Split('|');
                    //if the invoice id exists in invoices list then the statement matches against it.
                    if (matchBreakUp[0].IndexOf("~" + dtAuthList.Rows[y][0] + "~") >= 0)
                    {
                        //ensure that the statement is not already added.
                        if (matchBreakUp[1].IndexOf("~" + dtAuthList.Rows[y][1] + "~") < 0)
                        {
                            //if there are more statements than invoices or both equal then add a new row.
                            if (matchBreakUp[0].Length <= matchBreakUp[1].Length)
                            {
                                DataRow drStatement = dt.NewRow();
                                drStatement[1] = dtAuthList.Rows[y][1];
                                drStatement[6] = dtAuthList.Rows[y][6];
                                drStatement[7] = dtAuthList.Rows[y][7];
                                drStatement[8] = dtAuthList.Rows[y][8];
                                drStatement[9] = dtAuthList.Rows[y][9];
                                drStatement[10] = matchUniqueKey;
                                dt.Rows.Add(drStatement);
                            }
                            //otherwise add statement details in front of next invoice (statements < invoices)
                            else
                            {
                                //find next blank position for the statement, total rows - difference between number of invoices and number of statements
                                int nextStatementNumber = dt.Rows.Count - matchBreakUp[0].Split('~').Length + matchBreakUp[1].Split('~').Length;
                                dt.Rows[nextStatementNumber][1] = dtAuthList.Rows[y][1];
                                dt.Rows[nextStatementNumber][6] = dtAuthList.Rows[y][6];
                                dt.Rows[nextStatementNumber][7] = dtAuthList.Rows[y][7];
                                dt.Rows[nextStatementNumber][8] = dtAuthList.Rows[y][8];
                                dt.Rows[nextStatementNumber][9] = dtAuthList.Rows[y][9];
                            }
                            matchPatterns[x] = matchPatterns[x] + dtAuthList.Rows[y][1] + "~";
                        }
                    }
                    //if the statement id exists in statements list then the invoice matches against it.
                    else if (matchBreakUp[1].IndexOf("~" + dtAuthList.Rows[y][1] + "~") >= 0)
                    {
                        //ensure that the invoice is not already added.
                        if (matchBreakUp[0].IndexOf("~" + dtAuthList.Rows[y][0] + "~") < 0)
                        {
                            //if there are more invoices than statements or both equal then add a new row.
                            if (matchBreakUp[1].Length <= matchBreakUp[0].Length)
                            {
                                DataRow drInvoice = dt.NewRow();
                                drInvoice[0] = dtAuthList.Rows[y][0];
                                drInvoice[2] = dtAuthList.Rows[y][2];
                                drInvoice[3] = dtAuthList.Rows[y][3];
                                drInvoice[4] = dtAuthList.Rows[y][4];
                                drInvoice[5] = dtAuthList.Rows[y][5];
                                drInvoice[10] = matchUniqueKey;
                                dt.Rows.Add(drInvoice);
                            }
                            //otherwise add invoice details in front of next statement (invoices < statements)
                            else
                            {
                                //find next blank position for the invoice, total rows - difference between number of statements and number of invoices
                                int nextInvoiceNumber = dt.Rows.Count - matchBreakUp[1].Split('~').Length + matchBreakUp[0].Split('~').Length;
                                dt.Rows[nextInvoiceNumber][0] = dtAuthList.Rows[y][0];
                                dt.Rows[nextInvoiceNumber][2] = dtAuthList.Rows[y][2];
                                dt.Rows[nextInvoiceNumber][3] = dtAuthList.Rows[y][3];
                                dt.Rows[nextInvoiceNumber][4] = dtAuthList.Rows[y][4];
                                dt.Rows[nextInvoiceNumber][5] = dtAuthList.Rows[y][5];
                            }
                            matchPatterns[x] = matchPatterns[x].Replace("~|~", "~" + dtAuthList.Rows[y][0] + "~|~");
                        }
                    }
                    //neither invoice nor statement match
                    else
                    {
                        //no more match records in the group, jump to next group.
                        x = y - 1;
                        break;
                    }
                    //if last row has a match with some earlier one then value of x should be incremented to avoid looping back
                    if (y == dtAuthList.Rows.Count - 1)
                    {
                        x = y;
                    }
                }
            }

            Session[SessionStore.UnAuthorizedList] = dt;

            grdAuthList.DataSource = dt;
            grdAuthList.DataBind();
        }

        private void ProcessInvoices(ProcessType processType)
        {
            DataTable dtAuthList = (DataTable)Session[SessionStore.UnAuthorizedList];
            if (dtAuthList != null)
            {
                StringBuilder unmarkedIDList = new StringBuilder("~");
                foreach (GridViewRow authRow in grdAuthList.Rows)
                {
                    CheckBox chkSelect = (CheckBox)authRow.Cells[0].FindControl("chkSelect");
                    if (!chkSelect.Checked)
                    {
                        unmarkedIDList.Append(dtAuthList.Rows[authRow.RowIndex][10] + "~");
                    }
                }
                if (!unmarkedIDList.ToString().Equals("~"))
                {
                    for (int x = dtAuthList.Rows.Count - 1; x >= 0; x--)
                    {
                        if (unmarkedIDList.ToString().IndexOf("~" + dtAuthList.Rows[x][10].ToString() + "~") >= 0)
                        {
                            dtAuthList.Rows[x].Delete();
                        }
                    }
                }

                DataTable dt = new DataTable();
                dt.Columns.Add("invoice_unique_id", typeof(System.Int32));
                dt.Columns.Add("statement_unique_id", typeof(System.Int32));
                dt.Columns.Add("invoice_number", typeof(System.String));
                dt.Columns.Add("date", typeof(System.DateTime));
                dt.Columns.Add("remitter_id", typeof(System.String));
                dt.Columns.Add("amount", typeof(System.Double));
                dt.Columns.Add("ref_no_or_cheque_no", typeof(System.String));
                dt.Columns.Add("value_date", typeof(System.DateTime));
                dt.Columns.Add("narration1", typeof(System.String));
                dt.Columns.Add("statement_amount", typeof(System.Double));

                for (int x = 0; x < dtAuthList.Rows.Count; x++)
                {
                    int uniqueMatchKey = Convert.ToInt32(dtAuthList.Rows[x][10]);
                    if (!string.IsNullOrEmpty(dtAuthList.Rows[x][0].ToString()))
                    {
                        for (int y = 0; y < dtAuthList.Rows.Count; y++)
                        {
                            if (Convert.ToInt32(dtAuthList.Rows[y][10]) == uniqueMatchKey && !string.IsNullOrEmpty(dtAuthList.Rows[y][1].ToString()))
                            {
                                DataRow dr = dt.NewRow();
                                dr[0] = dtAuthList.Rows[x][0];
                                dr[2] = dtAuthList.Rows[x][2];
                                dr[3] = dtAuthList.Rows[x][3];
                                dr[4] = dtAuthList.Rows[x][4];
                                dr[5] = dtAuthList.Rows[x][5];
                                dr[1] = dtAuthList.Rows[y][1];
                                dr[6] = dtAuthList.Rows[y][6];
                                dr[7] = dtAuthList.Rows[y][7];
                                dr[8] = dtAuthList.Rows[y][8];
                                dr[9] = dtAuthList.Rows[y][9];
                                dt.Rows.Add(dr);
                            }
                        }
                    }
                }

                DBFactory db = new DBFactory();
                if (processType == ProcessType.Authorize)
                {
                    db.AuthorizeInvoices(((UserVO)Session["CurrentUserVO"]).customerId, ((UserVO)Session["CurrentUserVO"]).userId, dt);
                }
                else
                {
                    db.RejectInvoices(((UserVO)Session["CurrentUserVO"]).customerId, ((UserVO)Session["CurrentUserVO"]).userId, dt);
                }

                //get fresh list after database update and update UI
                GetUnauthorizedInvoiceList();
            }
        }

        protected void grdAuthList_RowDataBound(object sender, GridViewRowEventArgs e)
        {
            if (e.Row.RowIndex > -1)
            {
                DateTime dt;
                if (e.Row.Cells[2].Text != "" && e.Row.Cells[2].Text != "&nbsp;")
                {
                    dt = Convert.ToDateTime(e.Row.Cells[2].Text);
                    e.Row.Cells[2].Text = dt.ToString("dd-MM-yyyy");
                    e.Row.Cells[2].HorizontalAlign = HorizontalAlign.Center;
                }
                else
                {
                    e.Row.Cells[2].Text = "";
                }
                if (e.Row.Cells[6].Text != "" && e.Row.Cells[6].Text != "&nbsp;")
                {
                    dt = Convert.ToDateTime(e.Row.Cells[6].Text);
                    e.Row.Cells[6].Text = dt.ToString("dd-MM-yyyy");
                    e.Row.Cells[6].HorizontalAlign = HorizontalAlign.Center;
                }
                else
                {
                    e.Row.Cells[6].Text = "";
                }

                double value = 0.00;
                if (e.Row.Cells[4].Text != "" && e.Row.Cells[4].Text != "&nbsp;")
                {
                    value = Convert.ToDouble(e.Row.Cells[4].Text);
                    e.Row.Cells[4].Text = value.ToString("#,#.00", CultureInfo.InvariantCulture);
                    e.Row.Cells[4].HorizontalAlign = HorizontalAlign.Right;
                }
                else
                {
                    e.Row.Cells[4].Text = "0.00";
                }
                if (e.Row.Cells[8].Text != "" && e.Row.Cells[8].Text != "&nbsp;")
                {
                    value = Convert.ToDouble(e.Row.Cells[8].Text);
                    e.Row.Cells[8].Text = value.ToString("#,#.00", CultureInfo.InvariantCulture);
                    e.Row.Cells[8].HorizontalAlign = HorizontalAlign.Right;
                }
                else
                {
                    e.Row.Cells[8].Text = "0.00";
                }

            }       
        }
    }
}